package com.jemmyee.core.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * @author jemmyee
 * @date 2010-7-12
 * @param <T>
 */
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {
	
	
	private static final Log log = LogFactory.getLog(BaseDaoImpl.class);
	
	/**
	* @Description:该方法，防止在采用注解的情况下，会出现需要注入hibernateTemplate or SessionFactory的情况
	* @author:jemmyee@gmail.com
	* @date:2010-10-20
	*/
	@Autowired  
	 public void setSessionFactory0(SessionFactory sessionFactory){  
	  super.setSessionFactory(sessionFactory);  
	} 

	private Class<T> entityClass;
    
	public Class<T> getEntityClass() {
		return entityClass;
	}

	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public void delete(T entity) {
		getHibernateTemplate().delete(entity);
	}

	public void deleteById(Serializable id) {
//		String sql = "delete from " + entity.getClass().getSimpleName()+" where id="+id;
//		getHibernateTemplate().update(sql);
	}

	public List<T> findAll(T entity) {
		String queryString = "from " + entity.getClass().getSimpleName();
		return getHibernateTemplate().find(queryString);
	}

	public T findById(Serializable id) {
		return getHibernateTemplate().load(entityClass, id);
	}
	
	public List<T> findByProperty(T entity, String propertyName, Object value) {

		try {
			String queryString = "from " + entity.getClass().getSimpleName()
					+ " where " + propertyName + "='" + value + "' and 1=1";
			log.info(queryString);
			return getHibernateTemplate().find(queryString);
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	public void save(T entity) {
		getHibernateTemplate().save(entity);
	}

	public void update(T entity) {
		getHibernateTemplate().merge(entity);
	}
	
	@SuppressWarnings({ "deprecation", "unchecked" })
	public Page findPageByCriteria(final DetachedCriteria detachedCriteria,
			final int pageSize, final int startIndex,final String order) {
		return (Page) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Criteria criteria = detachedCriteria
						.getExecutableCriteria(session);
				long temp=((Long)criteria.setProjection(Projections.rowCount()).uniqueResult()).longValue();
				int totalCount = (Integer.parseInt(String.valueOf(temp)));
				criteria.setProjection(null);
				if(order != null && !order.equals("")){
					criteria.addOrder(Order.desc(order));
				}
				List items = criteria.setFirstResult(startIndex).setMaxResults(
						pageSize).list();
				Page ps = new Page(items, totalCount, pageSize, startIndex);
				return ps;
			}
		});
	}

	public List<T> findByCriteria(DetachedCriteria criteria) {
		return getHibernateTemplate().findByCriteria(criteria);
	}

	public void deleteAll(List<T> list){
		getHibernateTemplate().deleteAll(list);
	}
}
